import { deepMix, each } from '@antv/util';
import { polyline, labelCfg } from '@/graph/style/edge-style';

export default (G6) => {
  G6.registerEdge(`polyline-edge`, {
    timeout: [],
    timer: null,
    runners: [],
    setState(name, value, item) {

      const group = item.getContainer();

      if (name !== 'running') return;
      if (value) {
        return this.running(item.getModel(), group);
      }

      each(group.get('children'), (child) => {
        if (child.get('name') !== 'edge-runner') return;
        child.stopAnimate();
        this.runners.push(child);
      });

      each(this.runners, run => run.remove());
      each(this.timeout, timer => clearTimeout(timer));

      this.runners = [];
      this.timeout = [];
    },

    draw(cfg, group) {
      const { timer } = this;
      const keyShape = group.addShape('path', { name: 'edge-shape', attrs: deepMix({}, this.getShapeStyle(cfg), polyline, cfg.style) });

      if (timer) clearTimeout(timer);
      this.timer = setTimeout(() => {

        this.setState('running', false, group.get('item'));
        this.setState('running', true, group.get('item'));
        this.setLabel(cfg, group);
      }, 500);

      return keyShape;

    },

    running(cfg, group) {
      const edge = group.get('children')[0];
      const endArrowShape = edge.get('endArrowShape');
      const arrowSize = endArrowShape ? (endArrowShape.get('bbox') ? Math.max(endArrowShape.get('bbox').width, endArrowShape.get('bbox').height) : 0) : 0;
      const length = edge.getTotalLength();
      const num = Math.floor(length / 100) || 1;
      const { x, y } = edge.getPoint(0);
      if (length <= 40) return;

      for (let i = 0; i < num; i++) {
        const timeout = setTimeout(() => {

          const circle = group.addShape('circle', { name: 'edge-runner', visible: false, attrs: { fill: '#1890ff', r: 20, x, y, ...cfg.ball }, });

          function fn(ratio) {
            const { x, y } = edge.getPoint(ratio);
            const opacity = length - length * ratio >= arrowSize ? 1 : 0;

            circle.set('hasChanged', false);

            if (x > 0 && y > 0) circle.set('visible', true);

            return { x, y, opacity };
          }

          circle.animate(fn, { repeat: true, duration: length >= 100 ? length * 3 : length * 5 });
        }, i * length)
        this.timeout.push(timeout);
      }

    },

    setLabel(cfg, group) {
      const path = group.get('children')[0];
      group.addShape('text', {
        name: 'edge-label',
        attrs: deepMix(this.getLabelStyle(cfg, group), path.getPoint(0.5), { text: cfg.label, }, labelCfg)
      });
    },

    update: undefined,

  }, "polyline");
}